/*
		Code taken from PUTTY network abstraction.
		Rewrited to allow working with only single socket.

 */
#ifdef SOCK_IMPL
typedef struct SockAddr_tag *SockAddr;
typedef struct Socket_tag *Actual_Socket;
typedef struct socket_function_table **Socket;

#else
typedef void *SockAddr;
typedef void *Actual_Socket;
typedef void *Socket;
#endif


typedef struct plug_function_table **Plug;

struct plug_function_table {
    void (*log)(Socket sock, int type, SockAddr addr, int port,
		wchar_t *error_msg, int error_code, WPARAM app_param);
    /*
     * Passes the client progress reports on the process of setting
     * up the connection.
     * 
     * 	- type==0 means we are about to try to connect to address
     * 	  `addr' (error_msg and error_code are ignored)
     * 	- type==1 means we have failed to connect to address `addr'
     * 	  (error_msg and error_code are supplied). This is not a
     * 	  fatal error - we may well have other candidate addresses
     * 	  to fall back to. When it _is_ fatal, the closing()
     * 	  function will be called.
     */
    int (*closing)
     (Socket sock, wchar_t *error_msg, int error_code, int calling_back, WPARAM app_param);
    /* error_msg is NULL iff it is not an error (ie it closed normally) */
    /* calling_back != 0 iff there is a Plug function */
    /* currently running (would cure the fixme in try_send()) */
    int (*receive) (Socket sock, int urgent, char *data, int len, WPARAM app_param);
    /*
     *  - urgent==0. `data' points to `len' bytes of perfectly
     *    ordinary data.
     * 
     *  - urgent==1. `data' points to `len' bytes of data,
     *    which were read from before an Urgent pointer.
     * 
     *  - urgent==2. `data' points to `len' bytes of data,
     *    the first of which was the one at the Urgent mark.
     */
    void (*sent) (Socket sock, int bufsize,WPARAM app_param);
    /*
     * The `sent' function is called when the pending send backlog
     * on a socket is cleared or partially cleared. The new backlog
     * size is passed in the `bufsize' parameter.
     */
};

// do not change this!
#define WM_NETEVENT  (WM_APP + 1) 

typedef SockAddr (*NAME_LOOKUP_PROC)(wchar_t *host, int port, wchar_t **canonicalname,
		    int addressfamily);
typedef int (*SELECT_RESULT_PROC)(WPARAM wParam, LPARAM lParam, Socket s);
typedef Socket (*NEW_CONNECTION_PROC)(SockAddr addr, 
		      int port, int privport,
		      int oobinline, int nodelay, int keepalive,
		      Plug plug, HWND hwnd, WPARAM app_param);
typedef void (*NET_PENDING_ERRORS_PROC)(Socket s);
typedef void (*SK_ADDR_FREE_PROC)(SockAddr addr);
typedef void  (*SK_GETADDR_PROC)(SockAddr addr, wchar_t *buf, int buflen);
typedef int (*SK_WRITE_PROC)(Socket s, char *data, int len);
typedef void (*SK_SET_FROZEN_PROC)(Socket s, int is_frozen) ;
typedef void (*SK_CLOSE_PROC)(Socket s);
typedef wchar_t *(*SK_ADDR_ERROR_PROC)(SockAddr addr);
typedef const wchar_t *(*SK_SOCKET_ERROR_PROC)(Socket s);



/**************************************************************************************************

Simple rule of use:
- Create window
- Load library network.dll
- Implement pluggable functions (log, closing, receive, sent) 
- Override DefWindowProc and handle message WM_NETEVENT to call select_result
- create SockAddr struct pointer and set it to result of name_lookup (host resolving function)
- call function new_connection and store the result returned
This will provide asyncronous interface to the windows sockets. Defined pluggable function
will be called when corresponding event occurs. 
Remember that select_result could cause function reentry, for example when pluggable 
receive function will send something in responding on inbound data and thus generate 
FD_READ net event and call select_result again. This situation should be avoided, by using
reentrant flags for example.
Socket param is the value returned by new_connection.
hwnd is the window handle which will receive WM_NETEVENT message
app_param is an application defined value associated with the created socket


***************************************************************************************************/

